package com.jtbd.filters;

import com.jtbd.handler.JudgeTokenIsInvalidHandler;
import com.jtbd.config.SecurityWhiteUrlConfig;
import com.jtbd.constants.SecurityConstant;
import com.jtbd.exceptions.JtbdAuthenticationException;
import com.jtbd.handler.JtbdAuthenticationFailureHandler;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Resource
    private JtbdAuthenticationFailureHandler jtbdAuthenticationFailureHandler;
    @Resource
    private SecurityWhiteUrlConfig securityWhiteUrlConfig;
    @Resource
    private JudgeTokenIsInvalidHandler judgeTokenIsInvalidService;


    /**
     * 判断请求是否需要进行安全过滤
     *
     * @param request HTTP请求对象
     * @return true表示需要过滤，false表示不需要过滤
     */
    private boolean needFilter(HttpServletRequest request) {
        // 检查请求是否匹配任意一个白名单规则，如果不匹配任何白名单则需要过滤
        return !(securityWhiteUrlConfig.getWhiteListApiDocMatcher().matches(request) || securityWhiteUrlConfig.getWhiteListStaticMatcher().matches(request) || securityWhiteUrlConfig.getWhiteListCustomApiMatcher().matches(request));
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (needFilter(request)) {
            String token = request.getHeader(SecurityConstant.AUTH_HEADER);
            if (!StringUtils.hasLength(token)) {
                jtbdAuthenticationFailureHandler.onAuthenticationFailure(request, response, new JtbdAuthenticationException("token is not null"));
                return;
            }
            if (judgeTokenIsInvalidService.judgeTokenIsInvalid(token)) {
                jtbdAuthenticationFailureHandler.onAuthenticationFailure(request, response, new JtbdAuthenticationException("token is invalid"));
                return;
            }
            UsernamePasswordAuthenticationToken authentication = judgeTokenIsInvalidService.getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        filterChain.doFilter(request, response);
    }

}
